home *** CD-ROM | disk | FTP | other *** search
/ Aminet 44 / Aminet 44 (2001)(GTI - Schatztruhe)[!][Aug 2001].iso / Aminet / comm / mail / YAM23src.lha / Source / YAM_rexx.c < prev    next >
C/C++ Source or Header  |  2001-05-08  |  20KB  |  868 lines

  1. /***************************************************************************
  2.  
  3.  YAM - Yet Another Mailer
  4.  Copyright (C) 1995-2000 by Marcel Beck <mbeck@yam.ch>
  5.  Copyright (C) 2000-2001 by YAM Open Source Team
  6.  
  7.  This program is free software; you can redistribute it and/or modify
  8.  it under the terms of the GNU General Public License as published by
  9.  the Free Software Foundation; either version 2 of the License, or
  10.  (at your option) any later version.
  11.  
  12.  This program is distributed in the hope that it will be useful,
  13.  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  GNU General Public License for more details.
  16.  
  17.  You should have received a copy of the GNU General Public License
  18.  along with this program; if not, write to the Free Software
  19.  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  20.  
  21.  YAM Official Support Site :  http://www.yam.ch
  22.  YAM OpenSource project    :  http://sourceforge.net/projects/yamos/
  23.  
  24.  $Id: YAM_rexx.c,v 1.10 2001/05/08 22:27:37 damato Exp $
  25.  
  26. ***************************************************************************/
  27. /*
  28.  * Source generated with ARexxBox 1.12 (May 18 1993)
  29.  * And afterwards handmodified to fix bugs!
  30.  * which is Copyright (c) 1992,1993 Michael Balzer
  31.  */
  32.  
  33. #include <exec/types.h>
  34. #include <exec/memory.h>
  35. #include <dos/dos.h>
  36. #include <rexx/storage.h>
  37. #include <rexx/rxslib.h>
  38.  
  39. #ifdef __GNUC__
  40. /* GCC needs all struct defs */
  41. #include <dos/exall.h>
  42. #include <graphics/graphint.h>
  43. #include <intuition/classes.h>
  44. #include <devices/keymap.h>
  45. #include <exec/semaphores.h>
  46. #endif
  47.  
  48. #include <clib/alib_protos.h>
  49. #include <proto/exec.h>
  50. #include <proto/dos.h>
  51. #include <proto/rexxsyslib.h>
  52.  
  53. #include <stdlib.h>
  54. #include <stdio.h>
  55. #include <string.h>
  56. #include <ctype.h>
  57.  
  58. #ifdef LATTICE
  59. #undef toupper
  60. #endif
  61.  
  62. #include <dos/rdargs.h>
  63.  
  64. #include "YAM_rexx.h"
  65.  
  66. struct rxs_stemnode
  67. {
  68.    struct rxs_stemnode *succ;
  69.    char *name;
  70.    char *value;
  71. };
  72.  
  73.  
  74. extern struct ExecBase *SysBase;
  75. extern struct DosLibrary *DOSBase;
  76. extern struct RxsLib *RexxSysBase;
  77.  
  78. void (*ARexxResultHook)( struct RexxHost *, struct RexxMsg * ) = NULL;
  79.  
  80.  
  81.  
  82. void ReplyRexxCommand(
  83.    struct RexxMsg *rexxmessage,
  84.    long        primary,
  85.    long        secondary,
  86.    char        *result )
  87. {
  88.    if( rexxmessage->rm_Action & RXFF_RESULT )
  89.    {
  90.       if( primary == 0 )
  91.       {
  92.          secondary = result
  93.             ? (long) CreateArgstring( result, strlen(result) )
  94.             : (long) NULL;
  95.       }
  96.       else
  97.       {
  98.          char buf[16];
  99.          
  100.          if( primary > 0 )
  101.          {
  102.             sprintf( buf, "%ld", secondary );
  103.             result = buf;
  104.          }
  105.          else
  106.          {
  107.             primary = -primary;
  108.             result = (char *) secondary;
  109.          }
  110.          
  111.          SetRexxVar( rexxmessage, "RC2", result, strlen(result) );
  112.          
  113.          secondary = 0;
  114.       }
  115.    }
  116.    else if( primary < 0 )
  117.       primary = -primary;
  118.    
  119.    rexxmessage->rm_Result1 = primary;
  120.    rexxmessage->rm_Result2 = secondary;
  121.    ReplyMsg( (struct Message *) rexxmessage );
  122. }
  123.  
  124.  
  125. void FreeRexxCommand( struct RexxMsg *rexxmessage )
  126. {
  127.    if( !rexxmessage->rm_Result1 && rexxmessage->rm_Result2 )
  128.       DeleteArgstring( (char *) rexxmessage->rm_Result2 );
  129.  
  130.    if( rexxmessage->rm_Stdin &&
  131.       rexxmessage->rm_Stdin != Input() )
  132.       Close( rexxmessage->rm_Stdin );
  133.  
  134.    if( rexxmessage->rm_Stdout &&
  135.       rexxmessage->rm_Stdout != rexxmessage->rm_Stdin &&
  136.       rexxmessage->rm_Stdout != Output() )
  137.       Close( rexxmessage->rm_Stdout );
  138.  
  139.    DeleteArgstring( (char *) ARG0(rexxmessage) );
  140.    DeleteRexxMsg( rexxmessage );
  141. }
  142.  
  143.  
  144. struct RexxMsg *CreateRexxCommand( struct RexxHost *host, char *buff, BPTR fh )
  145. {
  146.    struct RexxMsg *rexx_command_message;
  147.  
  148.    if( (rexx_command_message = CreateRexxMsg( host->port,
  149.       rexx_extension, host->port->mp_Node.ln_Name)) == NULL )
  150.    {
  151.       return( NULL );
  152.    }
  153.  
  154.    if( (rexx_command_message->rm_Args[0] =
  155.       CreateArgstring(buff,strlen(buff))) == NULL )
  156.    {
  157.       DeleteRexxMsg(rexx_command_message);
  158.       return( NULL );
  159.    }
  160.  
  161.    rexx_command_message->rm_Action = RXCOMM | RXFF_RESULT;
  162.    rexx_command_message->rm_Stdin  = fh;
  163.    rexx_command_message->rm_Stdout = fh;
  164.    
  165.    return( rexx_command_message );
  166. }
  167.  
  168.  
  169. struct RexxMsg *CommandToRexx( struct RexxHost *host, struct RexxMsg *rexx_command_message )
  170. {
  171.    struct MsgPort *rexxport;
  172.    
  173.    Forbid();
  174.  
  175.    if( (rexxport = FindPort(RXSDIR)) == NULL )
  176.    {
  177.       Permit();
  178.       return( NULL );
  179.    }
  180.  
  181.    PutMsg( rexxport, &rexx_command_message->rm_Node );
  182.    
  183.    Permit();
  184.    
  185.    ++host->replies;
  186.    return( rexx_command_message );
  187. }
  188.  
  189.  
  190. struct RexxMsg *SendRexxCommand( struct RexxHost *host, char *buff, BPTR fh )
  191. {
  192.    struct RexxMsg *rcm;
  193.    
  194.    if( rcm = CreateRexxCommand(host, buff, fh) )
  195.       return CommandToRexx( host, rcm );
  196.    else
  197.       return NULL;
  198. }
  199.  
  200.  
  201. void CloseDownARexxHost( struct RexxHost *host )
  202. {
  203.    struct RexxMsg *rexxmsg;
  204.    
  205.    if( host->port )
  206.    {
  207.       /* Port abmelden */
  208.       RemPort( host->port );
  209.       
  210.       /* Auf noch ausstehende Replies warten */
  211.       while( host->replies > 0 )
  212.       {
  213.          WaitPort( host->port );
  214.          
  215.          while( rexxmsg = (struct RexxMsg *) GetMsg(host->port) )
  216.          {
  217.             if( rexxmsg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG )
  218.             {
  219.                if( !rexxmsg->rm_Args[15] )
  220.                {
  221.                   /* Reply zu einem SendRexxCommand()-Call */
  222.                   if( ARexxResultHook )
  223.                      ARexxResultHook( host, rexxmsg );
  224.                }
  225.                
  226.                FreeRexxCommand( rexxmsg );
  227.                --host->replies;
  228.             }
  229.             else
  230.                ReplyRexxCommand( rexxmsg, -20, (long) "Host closing down", NULL );
  231.          }
  232.       }
  233.       
  234.       /* MsgPort leeren */
  235.       while( rexxmsg = (struct RexxMsg *) GetMsg(host->port) )
  236.          ReplyRexxCommand( rexxmsg, -20, (long) "Host closing down", NULL );
  237.       
  238.       if( !(host->flags & ARB_HF_USRMSGPORT) )
  239.          DeleteMsgPort( host->port );
  240.    }
  241.    
  242.    if( host->rdargs ) FreeDosObject( DOS_RDARGS, host->rdargs );
  243.    FreeVec( host );
  244. }
  245.  
  246.  
  247. struct RexxHost *SetupARexxHost( char *basename, struct MsgPort *usrport )
  248. {
  249.    struct RexxHost *host;
  250.    int ext = 0;
  251.    
  252.    if( !basename )
  253.       basename = RexxPortBaseName;
  254.    else if( !*basename )
  255.       basename = RexxPortBaseName;
  256.    
  257.    if( !(host = AllocVec(sizeof(struct RexxHost), MEMF_CLEAR)) )
  258.       return NULL;
  259.    
  260.    strcpy( host->portname, basename );
  261.    
  262.    if( usrport )
  263.    {
  264.       host->port   = usrport;
  265.       host->flags |= ARB_HF_USRMSGPORT;
  266.    }
  267.    else if( !(host->port = CreateMsgPort()) )
  268.    {
  269.       FreeVec( host );
  270.       return NULL;
  271.    }
  272.    else
  273.    {
  274.       host->port->mp_Node.ln_Pri = 0;
  275.    }
  276.    
  277.    Forbid();
  278.    
  279.    while( FindPort(host->portname) )
  280.       sprintf( host->portname, "%s.%d", basename, ++ext );
  281.    
  282.    host->port->mp_Node.ln_Name = host->portname;
  283.    AddPort( host->port );
  284.    
  285.    Permit();
  286.    
  287.    if( !(host->rdargs = AllocDosObject(DOS_RDARGS, NULL)) )
  288.    {
  289.       RemPort( host->port );
  290.       if( !usrport ) DeleteMsgPort( host->port );
  291.       FreeVec( host );
  292.       return NULL;
  293.    }
  294.    
  295.    host->rdargs->RDA_Flags = RDAF_NOPROMPT;
  296.    
  297.    return( host );
  298. }
  299.  
  300.  
  301. /* StateMachine für FindRXCommand() */
  302.  
  303. static char *scmp( char *inp, char *str )
  304. {
  305.    while( *str && *inp )
  306.       if( *inp++ != *str++ )
  307.          return NULL;
  308.    
  309.    /* Reststring zurückgeben */
  310.    return inp;
  311. }
  312.  
  313. static int find( char *input )
  314. {
  315.    struct arb_p_state *st = arb_p_state;
  316.    struct arb_p_link *ad;
  317.    char *ni, tmp[36], *s;
  318.    
  319.    ni = tmp;
  320.    while( *input && ni-tmp < 32 )
  321.       *ni++ = toupper( *input++ );
  322.    *ni = 0;
  323.    input = tmp;
  324.    
  325.    while( *input )
  326.    {
  327.       /* Terminalzustand erreicht? */
  328.       if( !st->pa )
  329.       {
  330.          if( *input )
  331.             return -1;
  332.          else
  333.             return st->cmd;
  334.       }
  335.       
  336.       /* Wo geht's weiter? */
  337.       ni = 0;
  338.       for( ad = st->pa; s = ad->str; ad++ )
  339.       {
  340.          /* die Links sind absteigend sortiert */
  341.          if( *input > *s )
  342.             break;
  343.          
  344.          if( *input == *s )
  345.             if( ni = scmp(input+1, s+1) )
  346.                break;
  347.       }
  348.       
  349.       /* Nirgends... */
  350.       if( !ni )
  351.          return -1;
  352.       
  353.       /* Zustandsüberführung */
  354.       st = arb_p_state + ad->dst;
  355.       input = ni;
  356.    }
  357.    
  358.    return st->cmd;
  359. }
  360.  
  361. struct rxs_command *FindRXCommand( char *com )
  362. {
  363.    int cmd;
  364.    
  365.    cmd = find( com );
  366.    
  367.    if( cmd == -1 )
  368.       return NULL;
  369.    else
  370.       return( rxs_commandlist + cmd );
  371. }
  372.  
  373.  
  374. static struct rxs_command *ParseRXCommand( char **arg )
  375. {
  376.    char com[256], *s, *t;
  377.    
  378.    s = *arg;
  379.    t = com;
  380.    
  381.    while( *s && *s != ' ' && *s != '\n' )
  382.       *t++ = *s++;
  383.    
  384.    *t = '\0';
  385.    while( *s == ' ' ) ++s;
  386.    *arg = s;
  387.    
  388.    return( FindRXCommand( com ) );
  389. }
  390.  
  391.  
  392. static char *CreateVAR( struct rxs_stemnode *stem )
  393. {
  394.    char *var;
  395.    struct rxs_stemnode *s;
  396.    long size = 0;
  397.    
  398.    if( !stem || stem == (struct rxs_stemnode *) -1L )
  399.       return( (char *) stem );
  400.    
  401.    for( s = stem; s; s = s->succ )
  402.       size += strlen( s->value ) + 1;
  403.    
  404.    if( !(var = AllocVec( size + 1, MEMF_ANY )) )
  405.       return( (char *) -1 );
  406.    
  407.    *var = '\0';
  408.    
  409.    for( s = stem; s; s = s->succ )
  410.    {
  411.       strcat( var, s->value );
  412.       if( s->succ )
  413.          strcat( var, " " );
  414.    }
  415.    
  416.    return( var );
  417. }
  418.  
  419.  
  420. static struct rxs_stemnode *new_stemnode( struct rxs_stemnode **first, struct rxs_stemnode **old )
  421. {
  422.    struct rxs_stemnode *new;
  423.    
  424.    if( !(new = AllocVec(sizeof(struct rxs_stemnode), MEMF_CLEAR)) )
  425.    {
  426.       return( NULL );
  427.    }
  428.    else
  429.    {
  430.       if( *old )
  431.       {
  432.          (*old)->succ = new;
  433.          (*old) = new;
  434.       }
  435.       else
  436.       {
  437.          *first = *old = new;
  438.       }
  439.    }
  440.    
  441.    return( new );
  442. }
  443.  
  444.  
  445. static void free_stemlist( struct rxs_stemnode *first )
  446. {
  447.    struct rxs_stemnode *next;
  448.    
  449.    if( (long) first == -1 )
  450.       return;
  451.    
  452.    for( ; first; first = next )
  453.    {
  454.       next = first->succ;
  455.       if( first->name  ) FreeVec( first->name );
  456.       if( first->value ) FreeVec( first->value );
  457.       FreeVec( first );
  458.    }
  459. }
  460.  
  461.  
  462. char *StrDup( char *s )
  463. {
  464.    char *t = AllocVec( strlen(s)+1, MEMF_ANY );
  465.    if( t ) strcpy( t, s );
  466.    return t;
  467. }
  468.  
  469.  
  470. static struct rxs_stemnode *CreateSTEM( struct rxs_command *rxc, LONG *resarray, char *stembase )
  471. {
  472.    struct rxs_stemnode *first = NULL, *old = NULL, *new;
  473.    char resb[512], *rs, *rb;
  474.    char longbuff[16];
  475.    
  476.    rb = resb;
  477.    if( stembase )
  478.    {
  479.       while( *stembase )
  480.          *rb++ = toupper( *stembase++ );
  481.    }
  482.    *rb = '\0';
  483.    
  484.    rb = resb + strlen(resb);
  485.    rs = rxc->results;
  486.    
  487.    while( *rs )
  488.    {
  489.       char *t = rb;
  490.       BOOL optn = FALSE, optm = FALSE;
  491.       
  492.       while( *rs && *rs != ',' )
  493.       {
  494.          if( *rs == '/' )
  495.          {
  496.             ++rs;
  497.             if( *rs == 'N' ) optn = TRUE;
  498.             else if( *rs == 'M' ) optm = TRUE;
  499.          }
  500.          else
  501.             *t++ = *rs;
  502.          
  503.          ++rs;
  504.       }
  505.       
  506.       if( *rs == ',' ) ++rs;
  507.       *t = '\0';
  508.       
  509.       /*
  510.        * Resultat(e) erzeugen
  511.        */
  512.       
  513.       if( !*resarray )
  514.       {
  515.          ++resarray;
  516.          continue;
  517.       }
  518.       
  519.       if( optm )
  520.       {
  521.          long *r, index = 0;
  522.          LONG **subarray = (LONG **) *resarray++;
  523.          struct rxs_stemnode *countnd;
  524.          
  525.          /* Anzahl der Elemente */
  526.          
  527.          if( !(new = new_stemnode(&first, &old)) )
  528.          {
  529.             free_stemlist( first );
  530.             return( (struct rxs_stemnode *) -1L );
  531.          }
  532.          countnd = new;
  533.          
  534.          /* Die Elemente selbst */
  535.          
  536.          while( r = *subarray++ )
  537.          {
  538.             if( !(new = new_stemnode(&first, &old)) )
  539.             {
  540.                free_stemlist( first );
  541.                return( (struct rxs_stemnode *) -1L );
  542.             }
  543.             
  544.             sprintf( t, ".%ld", index++ );
  545.             new->name = StrDup( resb );
  546.             
  547.             if( optn )
  548.             {
  549.                sprintf( longbuff, "%ld", *r );
  550.                new->value = StrDup( longbuff );
  551.             }
  552.             else
  553.             {
  554.                new->value = StrDup( (char *) r );
  555.             }
  556.          }
  557.          
  558.          /* Die Count-Node */
  559.          
  560.          strcpy( t, ".COUNT" );
  561.          countnd->name = StrDup( resb );
  562.          
  563.          sprintf( longbuff, "%ld", index );
  564.          countnd->value = StrDup( longbuff );
  565.       }
  566.       else
  567.       {
  568.          /* Neue Node anlegen */
  569.          if( !(new = new_stemnode(&first, &old)) )
  570.          {
  571.             free_stemlist( first );
  572.             return( (struct rxs_stemnode *) -1L );
  573.          }
  574.          
  575.          new->name = StrDup( resb );
  576.          
  577.          if( optn )
  578.          {
  579.             sprintf( longbuff, "%ld", *((long *) *resarray) );
  580.             new->value = StrDup( longbuff );
  581.             ++resarray;
  582.          }
  583.          else
  584.          {
  585.             new->value = StrDup( (char *) (*resarray++) );
  586.          }
  587.       }
  588.    }
  589.    
  590.    return( first );
  591. }
  592.  
  593.  
  594. void DoRXCommand( struct RexxHost *host, struct RexxMsg *rexxmsg )
  595. {
  596.    struct rxs_command *rxc;
  597.    char *argb = NULL, *arg;
  598.    
  599.    LONG *array = NULL;
  600.    LONG *argarray;
  601.    LONG *resarray;
  602.    
  603.    char *cargstr = NULL;
  604.    long rc=20, rc2=0;
  605.    char *result = NULL;
  606.    
  607.    if( !(argb = AllocVec(strlen((char *) ARG0(rexxmsg)) + 2, MEMF_ANY)) )
  608.    {
  609.       rc2 = ERROR_NO_FREE_STORE;
  610.       goto drc_cleanup;
  611.    }
  612.    
  613.    /* welches Kommando? */
  614.    
  615.    strcpy( argb, (char *) ARG0(rexxmsg) );
  616.    strcat( argb, "\n" );
  617.    arg = argb;
  618.    
  619.    if( !( rxc = ParseRXCommand( &arg ) ) )
  620.    {
  621.       if( arg = ExpandRXCommand( host, (char *) ARG0(rexxmsg) ) )
  622.       {
  623.          FreeVec( argb );
  624.          if( !(argb = AllocVec( strlen(arg) + 2, MEMF_ANY )) )
  625.          {
  626.             rc2 = ERROR_NO_FREE_STORE;
  627.             goto drc_cleanup;
  628.          }
  629.          
  630.          strcpy( argb, arg );
  631.          strcat( argb, "\n" );
  632.          FreeVec( arg );
  633.          arg = argb;
  634.          
  635.          rxc = ParseRXCommand( &arg );
  636.       }
  637.    }
  638.    
  639.    if( !rxc )
  640.    {
  641.       /* Msg an ARexx schicken, vielleicht existiert ein Skript */
  642.       struct RexxMsg *rm;
  643.       
  644.       if( rm = CreateRexxCommand(host, (char *) ARG0(rexxmsg), NULL) )
  645.       {
  646.          /* Original-Msg merken */
  647.          rm->rm_Args[15] = (STRPTR) rexxmsg;
  648.          
  649.          if( CommandToRexx(host, rm) )
  650.          {
  651.             /* Reply wird später vom Dispatcher gemacht */
  652.             if( argb ) FreeVec( argb );
  653.             return;
  654.          }
  655.          else
  656.             rc2 = ERROR_NOT_IMPLEMENTED;
  657.       }
  658.       else
  659.          rc2 = ERROR_NO_FREE_STORE;
  660.       
  661.       goto drc_cleanup;
  662.    }
  663.    
  664.    if( !(rxc->flags & ARB_CF_ENABLED) )
  665.    {
  666.       rc = -10;
  667.       rc2 = (long) "Command disabled";
  668.       goto drc_cleanup;
  669.    }
  670.    
  671.    /* Speicher für Argumente etc. holen */
  672.    
  673.    (rxc->function)( host, (void **) &array, RXIF_INIT, rexxmsg );
  674.    cargstr = AllocVec( rxc->args ? 15+strlen(rxc->args) : 15, MEMF_ANY );
  675.    
  676.    if( !array || !cargstr )
  677.    {
  678.       rc2 = ERROR_NO_FREE_STORE;
  679.       goto drc_cleanup;
  680.    }
  681.    
  682.    argarray = array + 2;
  683.    resarray = array + rxc->resindex;
  684.    
  685.    /* Argumente parsen */
  686.    
  687.    if( rxc->results )
  688.       strcpy( cargstr, "VAR/K,STEM/K" );
  689.    else
  690.       *cargstr = '\0';
  691.    
  692.    if( rxc->args )
  693.    {
  694.       if( *cargstr )
  695.          strcat( cargstr, "," );
  696.       strcat( cargstr, rxc->args );
  697.    }
  698.    
  699.    if( *cargstr )
  700.    {
  701.       host->rdargs->RDA_Source.CS_Buffer = arg;
  702.       host->rdargs->RDA_Source.CS_Length = strlen(arg);
  703.       host->rdargs->RDA_Source.CS_CurChr = 0;
  704.       host->rdargs->RDA_DAList = NULL;
  705.       host->rdargs->RDA_Buffer = NULL;
  706.       
  707.       if( !ReadArgs(cargstr, argarray, host->rdargs) )
  708.       {
  709.          rc = 10;
  710.          rc2 = IoErr();
  711.          goto drc_cleanup;
  712.       }
  713.    }
  714.    
  715.    /* Funktion aufrufen */
  716.    
  717.    (rxc->function)( host, (void **) &array, RXIF_ACTION, rexxmsg );
  718.    
  719.    rc = array[0];
  720.    rc2 = array[1];
  721.    
  722.    /* Resultat(e) auswerten */
  723.    
  724.    if( rxc->results && rc==0 &&
  725.       (rexxmsg->rm_Action & RXFF_RESULT) )
  726.    {
  727.       struct rxs_stemnode *stem, *s;
  728.       
  729.       stem = CreateSTEM( rxc, resarray, (char *)argarray[1] );
  730.       result = CreateVAR( stem );
  731.       
  732.       if( result )
  733.       {
  734.          if( argarray[0] )
  735.          {
  736.             /* VAR */
  737.             if( (long) result == -1 )
  738.             {
  739.                rc = 20;
  740.                rc2 = ERROR_NO_FREE_STORE;
  741.             }
  742.             else
  743.             {
  744.                char *rb;
  745.                
  746.                for( rb = (char *) argarray[0]; *rb; ++rb )
  747.                   *rb = toupper( *rb );
  748.                
  749.                if( SetRexxVar( rexxmsg,
  750.                   *((char *)argarray[0]) ? (char *)argarray[0] : "RESULT",
  751.                   result, strlen(result) ) )
  752.                {
  753.                   rc = -10;
  754.                   rc2 = (long) "Unable to set Rexx variable";
  755.                }
  756.                
  757.                FreeVec( result );
  758.             }
  759.             
  760.             result = NULL;
  761.          }
  762.          
  763.          if( !rc && argarray[1] )
  764.          {
  765.             /* STEM */
  766.             if( (long) stem == -1 )
  767.             {
  768.                rc = 20;
  769.                rc2 = ERROR_NO_FREE_STORE;
  770.             }
  771.             else
  772.             {
  773.                for( s = stem; s; s = s->succ )
  774.                   rc |= SetRexxVar( rexxmsg, s->name, s->value, strlen(s->value) );
  775.                
  776.                if( rc )
  777.                {
  778.                   rc = -10;
  779.                   rc2 = (long) "Unable to set Rexx variable";
  780.                }
  781.                
  782.                if( result && (long) result != -1 )
  783.                   FreeVec( result );
  784.             }
  785.             
  786.             result = NULL;
  787.          }
  788.          
  789.          /* Normales Resultat: Möglich? */
  790.          
  791.          if( (long) result == -1 )
  792.          {
  793.             /* Nein */
  794.             rc = 20;
  795.             rc2 = ERROR_NO_FREE_STORE;
  796.             result = NULL;
  797.          }
  798.       }
  799.       
  800.       free_stemlist( stem );
  801.    }
  802.    
  803. drc_cleanup:
  804.  
  805.    /* Nur RESULT, wenn weder VAR noch STEM */
  806.    
  807.    ReplyRexxCommand( rexxmsg, rc, rc2, result );
  808.    
  809.    /* benutzten Speicher freigeben */
  810.    
  811.    if( result ) FreeVec( result );
  812.    FreeArgs( host->rdargs );
  813.    if( cargstr ) FreeVec( cargstr );
  814.    if( array ) (rxc->function)( host, (void **) &array, RXIF_FREE, rexxmsg );
  815.    if( argb ) FreeVec( argb );
  816. }
  817.  
  818.  
  819. void ARexxDispatch( struct RexxHost *host )
  820. {
  821.    struct RexxMsg *rexxmsg;
  822.  
  823.    while( rexxmsg = (struct RexxMsg *) GetMsg(host->port) )
  824.    {
  825.       if( (rexxmsg->rm_Action & RXCODEMASK) != RXCOMM )
  826.       {
  827.          /* Keine Rexx-Message */
  828.          ReplyMsg( (struct Message *) rexxmsg );
  829.       }
  830.       else if( rexxmsg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG )
  831.       {
  832.          struct RexxMsg *org = (struct RexxMsg *) rexxmsg->rm_Args[15];
  833.          
  834.          if( org )
  835.          {
  836.             /* Reply zu durchgereichter Msg */
  837.             if( rexxmsg->rm_Result1 != 0 )
  838.             {
  839.                /* Befehl unbekannt */
  840.                ReplyRexxCommand( org, 20, ERROR_NOT_IMPLEMENTED, NULL );
  841.             }
  842.             else
  843.             {
  844.                ReplyRexxCommand( org, 0, 0, (char *) rexxmsg->rm_Result2 );
  845.             }
  846.          }
  847.          else
  848.          {
  849.             /* Reply zu einem SendRexxCommand()-Call */
  850.             if( ARexxResultHook )
  851.                ARexxResultHook( host, rexxmsg );
  852.          }
  853.          
  854.          FreeRexxCommand( rexxmsg );
  855.          --host->replies;
  856.       }
  857.       else if( ARG0(rexxmsg) )
  858.       {
  859.          DoRXCommand( host, rexxmsg );
  860.       }
  861.       else
  862.       {
  863.          ReplyMsg( (struct Message *) rexxmsg );
  864.       }
  865.    }
  866. }
  867.  
  868.